package com.hu.system.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.hu.common.utils.StringUtils;
import com.hu.system.domain.PurchaseInbound;
import com.hu.system.domain.ProductInfo;
import com.hu.system.domain.ShopInfo;
import com.hu.system.domain.StockInbound;
import com.hu.system.service.IProductInfoService;
import com.hu.system.service.IShopInfoService;
import com.hu.system.mapper.PurchaseInboundMapper;
import com.hu.system.mapper.ProductInfoMapper;
import com.hu.system.mapper.StockInboundMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 采购入库导入监听器
 * 使用无模型读取和手动列映射，支持动态表头识别
 *
 * @author hu-erp
 */
public class PurchaseInboundImportListener extends AnalysisEventListener<Map<Integer, String>> {

    private static final Logger log = LoggerFactory.getLogger(PurchaseInboundImportListener.class);

    /**
     * 每隔100条存储数据库
     */
    private static final int BATCH_COUNT = 100;

    private List<PurchaseInbound> batchList = new ArrayList<>();

    private final IProductInfoService productInfoService;
    private final IShopInfoService shopInfoService;
    private final PurchaseInboundMapper purchaseInboundMapper;
    private final ProductInfoMapper productInfoMapper;
    private final StockInboundMapper stockInboundMapper;
    private final String createBy;
    private final String importRemark;
    private final int expectedHeadRowNumber;
    private final Map<String, Integer> columnMap;

    /** 内存缓存：避免同一请求重复查库 */
    private Map<String, ShopInfo> shopCache = new HashMap<>();
    private Map<String, ProductInfo> productCache = new HashMap<>();

    // 统计信息
    private int successNum = 0;
    private int failureNum = 0;
    private StringBuilder failureMsg = new StringBuilder();
    private int createdProductCount = 0;
    private int updatedProductCount = 0;
    private int createdShopCount = 0;
    private List<String> updatedProductDetails = new ArrayList<>();
    
    // 上一行的店铺ID，用于自动沿用
    private Long lastShopId = null;
    private String lastShopName = null;

    public PurchaseInboundImportListener(IProductInfoService productInfoService,
                                         IShopInfoService shopInfoService,
                                         PurchaseInboundMapper purchaseInboundMapper,
                                         ProductInfoMapper productInfoMapper,
                                         StockInboundMapper stockInboundMapper,
                                         String createBy,
                                         int expectedHeadRowNumber,
                                         Map<String, Integer> columnMap) {
        this.productInfoService = productInfoService;
        this.shopInfoService = shopInfoService;
        this.purchaseInboundMapper = purchaseInboundMapper;
        this.productInfoMapper = productInfoMapper;
        this.stockInboundMapper = stockInboundMapper;
        this.createBy = createBy;
        this.importRemark = "【导入于 " + com.hu.common.utils.DateUtils.getTime() + "】";
        this.expectedHeadRowNumber = expectedHeadRowNumber;
        this.columnMap = columnMap;
    }

    @Override
    public void invoke(Map<Integer, String> rowData, AnalysisContext context) {
        // 声明变量在外部，让catch块也能访问
        PurchaseInbound purchaseInbound = null;
        
        try {
            // 获取当前行号
            int currentRowIndex = context.readRowHolder().getRowIndex();
            
            // 跳过表头行及之前的行
            if (currentRowIndex <= expectedHeadRowNumber) {
                return;
            }
            
            // 手动从Map中提取数据并创建PurchaseInbound对象
            purchaseInbound = mapRowToPurchaseInbound(rowData);
            if (purchaseInbound == null) {
                // 空行或无效行，直接跳过，不计入失败统计
                return;
            }
            
            // 此时 purchaseInbound 不为 null，且 SKU 也不为空（在 mapRowToPurchaseInbound 中已确保）

            // 处理店铺：从Excel读取店铺名称，查询或创建店铺
            Long currentShopId = null;
            String currentShopName = null;
            
            if (StringUtils.isNotEmpty(purchaseInbound.getShopName())) {
                // Excel中有店铺名称，从缓存或数据库获取
                currentShopName = purchaseInbound.getShopName();
                ShopInfo shop = shopCache.get(currentShopName);
                if (shop == null) {
                    // 缓存中没有，查询或创建
                    shop = shopInfoService.getOrCreateShopByName(currentShopName, createBy);
                    shopCache.put(currentShopName, shop);

                    // 统计新建店铺
                    if (shop.getCreateBy() != null && shop.getCreateBy().equals(createBy)) {
                        createdShopCount++;
                    }
                }
                currentShopId = shop.getShopId();
                
                // 记录当前行的店铺信息，供下一行沿用
                lastShopId = currentShopId;
                lastShopName = currentShopName;
            } else if (lastShopId != null) {
                // Excel中无店铺名称，自动沿用上一行的店铺
                currentShopId = lastShopId;
                currentShopName = lastShopName;
                log.debug("SKU[{}] 自动沿用上一行的店铺：{}", purchaseInbound.getSku(), lastShopName);
            } else {
                // Excel中无店铺且上一行也没有店铺，报错
                failureNum++;
                failureMsg.append("<br/>SKU[" + purchaseInbound.getSku() + "]：所属店铺不能为空（第一行数据必须填写店铺名称）");
                return;
            }
            
            purchaseInbound.setShopId(currentShopId);
            if (StringUtils.isEmpty(purchaseInbound.getShopName())) {
                purchaseInbound.setShopName(currentShopName);
            }

            // 校验必填字段：采购数量
            if (purchaseInbound.getPurchaseQuantity() == null || purchaseInbound.getPurchaseQuantity() <= 0) {
                failureNum++;
                failureMsg.append("<br/>SKU[" + purchaseInbound.getSku() + "]：采购数量不能为空且必须大于0");
                return;
            }

            // 校验必填字段：采购总金额
            if (purchaseInbound.getPurchaseAmount() == null || purchaseInbound.getPurchaseAmount().compareTo(BigDecimal.ZERO) <= 0) {
                failureNum++;
                failureMsg.append("<br/>SKU[" + purchaseInbound.getSku() + "]：采购总金额不能为空且必须大于0");
                return;
            }

            // 校验必填字段：采购入库日期
            if (purchaseInbound.getPurchaseDate() == null) {
                failureNum++;
                failureMsg.append("<br/>SKU[" + purchaseInbound.getSku() + "]：采购入库日期不能为空");
                return;
            }

            // 处理包装费：Excel中的单品包装费已经是每件商品的包装费，直接使用
            if (purchaseInbound.getPackageFee() == null) {
                purchaseInbound.setPackageFee(BigDecimal.ZERO);
            }
            // 不再需要除以数量，直接使用Excel中的值

            // 检查产品是否存在（使用缓存避免重复查询），不存在则自动创建
            String productCacheKey = purchaseInbound.getSku() + "_" + currentShopId;
            ProductInfo product = productCache.get(productCacheKey);

            if (product == null) {
                // 缓存中没有，调用服务查询或创建
                com.hu.system.domain.ProductOperationResult operationResult = productInfoService.getOrCreateProduct(
                        purchaseInbound.getSku(),
                        purchaseInbound.getProductName(),
                        purchaseInbound.getSkuAttr(),
                        purchaseInbound.getSkuCode(),  // 传入SKU货号，如果为空服务层会设置为sku
                        currentShopId
                );
                product = operationResult.getProduct();
                productCache.put(productCacheKey, product);

                // 如果导入数据中包含平台核价，则更新产品的核价字段
                if (purchaseInbound.getPriceCheck() != null && purchaseInbound.getPriceCheck().compareTo(BigDecimal.ZERO) > 0) {
                    product.setPriceCheck(purchaseInbound.getPriceCheck());
                    product.setUpdateBy(createBy);
                    productInfoMapper.updateProductInfo(product);

                    if (operationResult.getOperationType() == com.hu.system.domain.ProductOperationResult.OperationType.CREATED) {
                        updatedProductDetails.add("SKU[" + purchaseInbound.getSku() + "] 新建并设置核价");
                    } else {
                        updatedProductDetails.add("SKU[" + purchaseInbound.getSku() + "] 更新核价");
                    }
                }

                // 统计产品操作
                if (operationResult.getOperationType() == com.hu.system.domain.ProductOperationResult.OperationType.CREATED) {
                    createdProductCount++;
                } else if (operationResult.getOperationType() == com.hu.system.domain.ProductOperationResult.OperationType.UPDATED) {
                    updatedProductCount++;
                    updatedProductDetails.add("SKU[" + purchaseInbound.getSku() + "]" + operationResult.getUpdateDescription());
                }
            }
            // 如果缓存中有产品，直接使用（已在上面的 if 中处理）

            // 从产品信息中补充字段
            if (product != null) {
                if (StringUtils.isEmpty(purchaseInbound.getProductName())) {
                    purchaseInbound.setProductName(product.getProductName());
                }
                if (StringUtils.isEmpty(purchaseInbound.getSkuAttr())) {
                    purchaseInbound.setSkuAttr(product.getSkuAttr());
                }
            }

            // 自动计算产品单价：unit_price = purchase_amount / purchase_quantity + package_fee
            calculateUnitPrice(purchaseInbound);

            // 添加导入备注
            if (StringUtils.isEmpty(purchaseInbound.getRemark())) {
                purchaseInbound.setRemark(importRemark);
            } else {
                purchaseInbound.setRemark(purchaseInbound.getRemark() + " " + importRemark);
            }

            // 设置基础字段
            purchaseInbound.setDelFlag("0");
            purchaseInbound.setCreateBy(createBy);

            // 添加到批量列表
            batchList.add(purchaseInbound);
            successNum++;

            // 达到BATCH_COUNT，需要去存储一次数据库
            if (batchList.size() >= BATCH_COUNT) {
                saveData();
            }

        } catch (Exception e) {
            failureNum++;
            String sku = (purchaseInbound != null && purchaseInbound.getSku() != null) ? purchaseInbound.getSku() : "未知";
            String msg = "<br/>" + (successNum + failureNum) + "、SKU[" + sku + "] 处理失败：";
            failureMsg.append(msg + e.getMessage());
            log.error("导入数据处理失败，SKU: {}", sku, e);
        }
    }

    /**
     * 手动将行数据映射到PurchaseInbound对象
     */
    private PurchaseInbound mapRowToPurchaseInbound(Map<Integer, String> rowData) {
        // 判断是否为空行
        boolean isEmpty = rowData.values().stream().allMatch(v -> v == null || v.trim().isEmpty());
        if (isEmpty) {
            return null;
        }
        
        PurchaseInbound entity = new PurchaseInbound();
        
        // 根据列映射提取数据
        entity.setSku(getColumnValueAsText(rowData, "SKU ID"));
        entity.setProductName(getColumnValue(rowData, "产品名称"));
        entity.setSkuAttr(getColumnValue(rowData, "SKU属性"));
        entity.setSkuCode(getColumnValueAsText(rowData, "SKU货号"));
        entity.setShopName(getColumnValue(rowData, "所属店铺"));
        entity.setRemark(getColumnValue(rowData, "备注/原因", "备注"));
        
        // 数值类型字段
        entity.setPurchaseQuantity(parseInteger(getColumnValue(rowData, "采购数量")));
        entity.setPurchaseAmount(parseBigDecimal(getColumnValue(rowData, "采购金额", "采购总金额")));
        entity.setPackageFee(parseBigDecimal(getColumnValue(rowData, "单品包装费", "包装费")));
        entity.setPriceCheck(parseBigDecimal(getColumnValue(rowData, "核价", "平台核价")));
        
        // 日期字段
        entity.setPurchaseDate(parseDate(getColumnValue(rowData, "日期", "采购日期", "采购入库日期")));
        
        // 二次判断：如果SKU为空，说明是空行或无效行
        if (StringUtils.isEmpty(entity.getSku())) {
            return null;
        }
        
        return entity;
    }
    
    /**
     * 获取列值（支持多个可能的列名）
     */
    private String getColumnValue(Map<Integer, String> rowData, String... possibleColumnNames) {
        for (String columnName : possibleColumnNames) {
            Integer columnIndex = columnMap.get(columnName);
            if (columnIndex != null) {
                String value = rowData.get(columnIndex);
                if (value != null && !value.trim().isEmpty()) {
                    return value.trim();
                }
            }
        }
        return null;
    }
    
    /**
     * 获取文本列值（去除数字格式化）
     * 用于SKU、SKU货号等字段
     */
    private String getColumnValueAsText(Map<Integer, String> rowData, String... possibleColumnNames) {
        String value = getColumnValue(rowData, possibleColumnNames);
        if (value == null) {
            return null;
        }
        
        // 去除数字格式化：千分位逗号和末尾的.00
        value = value.replace(",", "");
        if (value.matches(".*\\.0+$")) {
            value = value.replaceAll("\\.0+$", "");
        }
        
        return value;
    }
    
    private Integer parseInteger(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            return Integer.parseInt(value.trim());
        } catch (Exception e) {
            return null;
        }
    }
    
    private BigDecimal parseBigDecimal(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            return new BigDecimal(value.trim());
        } catch (Exception e) {
            return BigDecimal.ZERO;
        }
    }
    
    private java.util.Date parseDate(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            return com.hu.common.utils.DateUtils.parseDate(value.trim());
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 保存剩余数据
        saveData();
        log.info("所有数据解析完成，成功{}条，失败{}条", successNum, failureNum);
    }

    /**
     * 批量保存数据
     */
    private void saveData() {
        if (!batchList.isEmpty()) {
            // 插入采购记录
            purchaseInboundMapper.batchInsertPurchaseInbound(new ArrayList<>(batchList));

            // 同步创建库存入库记录
            List<StockInbound> stockInboundList = new ArrayList<>();
            for (PurchaseInbound pi : batchList) {
                StockInbound stockInbound = new StockInbound();
                stockInbound.setSku(pi.getSku());
                stockInbound.setProductName(pi.getProductName());
                stockInbound.setShopId(pi.getShopId());
                stockInbound.setInboundQuantity(pi.getPurchaseQuantity());
                stockInbound.setInboundType("PURCHASE");
                stockInbound.setSourceId(pi.getInboundId());
                stockInbound.setInboundDate(pi.getPurchaseDate());
                stockInbound.setRemark("采购入库：" + (pi.getRemark() != null ? pi.getRemark() : ""));
                stockInbound.setDelFlag("0");
                stockInbound.setCreateBy(createBy);
                stockInboundList.add(stockInbound);
            }
            stockInboundMapper.batchInsertStockInbound(stockInboundList);

            log.info("批量保存{}条数据到数据库", batchList.size());
            batchList.clear();
            stockInboundList.clear();
        }
    }

    /**
     * 计算产品单价
     */
    private void calculateUnitPrice(PurchaseInbound purchaseInbound) {
        if (purchaseInbound.getPurchaseAmount() != null && purchaseInbound.getPurchaseQuantity() != null && purchaseInbound.getPurchaseQuantity() > 0) {
            BigDecimal unitPrice = purchaseInbound.getPurchaseAmount()
                    .divide(new BigDecimal(purchaseInbound.getPurchaseQuantity()), 2, RoundingMode.HALF_UP);
            if (purchaseInbound.getPackageFee() != null) {
                unitPrice = unitPrice.add(purchaseInbound.getPackageFee());
            }
            purchaseInbound.setUnitPrice(unitPrice);
        }
    }

    /**
     * 获取导入结果
     */
    public String getResult() {
        StringBuilder resultMsg = new StringBuilder();

        if (failureNum > 0) {
            resultMsg.append("导入完成！成功 " + successNum + " 条，失败 " + failureNum + " 条");
        } else {
            resultMsg.append("恭喜您，数据已全部导入成功！共 " + successNum + " 条");
        }

        // 添加店铺操作统计
        if (createdShopCount > 0) {
            resultMsg.append("<br/><br/>【店铺处理统计】");
            resultMsg.append("<br/>新建店铺：" + createdShopCount + " 个");
        }

        // 添加产品操作统计
        if (createdProductCount > 0 || updatedProductCount > 0) {
            resultMsg.append("<br/><br/>【产品处理统计】");
            if (createdProductCount > 0) {
                resultMsg.append("<br/>新建产品：" + createdProductCount + " 个");
            }
            if (updatedProductCount > 0) {
                resultMsg.append("<br/>更新产品：" + updatedProductCount + " 个");
                if (!updatedProductDetails.isEmpty()) {
                    resultMsg.append("<br/>更新详情：");
                    int displayCount = Math.min(10, updatedProductDetails.size());
                    for (int i = 0; i < displayCount; i++) {
                        resultMsg.append("<br/>  · " + updatedProductDetails.get(i));
                    }
                    if (updatedProductDetails.size() > 10) {
                        resultMsg.append("<br/>  · ... 还有 " + (updatedProductDetails.size() - 10) + " 条更新");
                    }
                }
            }
        }

        if (failureNum > 0) {
            resultMsg.append("<br/><br/>【失败明细】");
            resultMsg.append(failureMsg);
        }

        return resultMsg.toString();
    }
}

